home *** CD-ROM | disk | FTP | other *** search
- Subject: v14i080: Flex, a lex replacement, Part02/05
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Vern Paxson <vern@lbl-csam.arpa>
- Posting-number: Volume 14, Issue 80
- Archive-name: flex/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 5)."
- # Contents: dfa.c flex.fastskel main.c misc.c scan.l
- # Wrapped by rsalz@fig.bbn.com on Tue May 3 17:31:27 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'dfa.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dfa.c'\"
- else
- echo shar: Extracting \"'dfa.c'\" \(10732 characters\)
- sed "s/^X//" >'dfa.c' <<'END_OF_FILE'
- X/* dfa - DFA construction routines */
- X
- X/*
- X * Copyright (c) 1987, the University of California
- X *
- X * The United States Government has rights in this work pursuant to
- X * contract no. DE-AC03-76SF00098 between the United States Department of
- X * Energy and the University of California.
- X *
- X * This program may be redistributed. Enhancements and derivative works
- X * may be created provided the new works, if made available to the general
- X * public, are made available for use by anyone.
- X */
- X
- X#include "flexdef.h"
- X
- X/* epsclosure - construct the epsilon closure of a set of ndfa states
- X *
- X * synopsis
- X * int t[current_max_dfa_size], numstates, accset[accnum + 1], nacc;
- X * int hashval;
- X * int *epsclosure();
- X * t = epsclosure( t, &numstates, accset, &nacc, &hashval );
- X *
- X * NOTES
- X * the epsilon closure is the set of all states reachable by an arbitrary
- X * number of epsilon transitions which themselves do not have epsilon
- X * transitions going out, unioned with the set of states which have non-null
- X * accepting numbers. t is an array of size numstates of nfa state numbers.
- X * Upon return, t holds the epsilon closure and numstates is updated. accset
- X * holds a list of the accepting numbers, and the size of accset is given
- X * by nacc. t may be subjected to reallocation if it is not large enough
- X * to hold the epsilon closure.
- X *
- X * hashval is the hash value for the dfa corresponding to the state set
- X */
- X
- int *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
- int *t, *ns_addr, accset[], *nacc_addr, *hv_addr;
- X
- X {
- X register int stkpos, ns, tsp;
- X int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
- X int stkend, nstate;
- X static int did_stk_init = false, *stk;
- X
- X#define MARK_STATE(state) \
- X trans1[state] = trans1[state] - MARKER_DIFFERENCE;
- X
- X#define IS_MARKED(state) (trans1[state] < 0)
- X
- X#define UNMARK_STATE(state) \
- X trans1[state] = trans1[state] + MARKER_DIFFERENCE;
- X
- X#define CHECK_ACCEPT(state) \
- X { \
- X nfaccnum = accptnum[state]; \
- X if ( nfaccnum != NIL ) \
- X accset[++nacc] = nfaccnum; \
- X }
- X
- X#define DO_REALLOCATION \
- X { \
- X current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
- X ++num_reallocs; \
- X t = reallocate_integer_array( t, current_max_dfa_size ); \
- X stk = reallocate_integer_array( stk, current_max_dfa_size ); \
- X } \
- X
- X#define PUT_ON_STACK(state) \
- X { \
- X if ( ++stkend >= current_max_dfa_size ) \
- X DO_REALLOCATION \
- X stk[stkend] = state; \
- X MARK_STATE(state) \
- X }
- X
- X#define ADD_STATE(state) \
- X { \
- X if ( ++numstates >= current_max_dfa_size ) \
- X DO_REALLOCATION \
- X t[numstates] = state; \
- X hashval = hashval + state; \
- X }
- X
- X#define STACK_STATE(state) \
- X { \
- X PUT_ON_STACK(state) \
- X CHECK_ACCEPT(state) \
- X if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
- X ADD_STATE(state) \
- X }
- X
- X if ( ! did_stk_init )
- X {
- X stk = allocate_integer_array( current_max_dfa_size );
- X did_stk_init = true;
- X }
- X
- X nacc = stkend = hashval = 0;
- X
- X for ( nstate = 1; nstate <= numstates; ++nstate )
- X {
- X ns = t[nstate];
- X
- X /* the state could be marked if we've already pushed it onto
- X * the stack
- X */
- X if ( ! IS_MARKED(ns) )
- X PUT_ON_STACK(ns)
- X
- X CHECK_ACCEPT(ns)
- X hashval = hashval + ns;
- X }
- X
- X for ( stkpos = 1; stkpos <= stkend; ++stkpos )
- X {
- X ns = stk[stkpos];
- X transsym = transchar[ns];
- X
- X if ( transsym == SYM_EPSILON )
- X {
- X tsp = trans1[ns] + MARKER_DIFFERENCE;
- X
- X if ( tsp != NO_TRANSITION )
- X {
- X if ( ! IS_MARKED(tsp) )
- X STACK_STATE(tsp)
- X
- X tsp = trans2[ns];
- X
- X if ( tsp != NO_TRANSITION )
- X if ( ! IS_MARKED(tsp) )
- X STACK_STATE(tsp)
- X }
- X }
- X }
- X
- X /* clear out "visit" markers */
- X
- X for ( stkpos = 1; stkpos <= stkend; ++stkpos )
- X {
- X if ( IS_MARKED(stk[stkpos]) )
- X {
- X UNMARK_STATE(stk[stkpos])
- X }
- X else
- X flexfatal( "consistency check failed in epsclosure()" );
- X }
- X
- X *ns_addr = numstates;
- X *hv_addr = hashval;
- X *nacc_addr = nacc;
- X
- X return ( t );
- X }
- X
- X
- X
- X/* increase_max_dfas - increase the maximum number of DFAs */
- X
- increase_max_dfas()
- X
- X {
- X int old_max = current_max_dfas;
- X
- X current_max_dfas += MAX_DFAS_INCREMENT;
- X
- X ++num_reallocs;
- X
- X base = reallocate_integer_array( base, current_max_dfas );
- X def = reallocate_integer_array( def, current_max_dfas );
- X dfasiz = reallocate_integer_array( dfasiz, current_max_dfas );
- X accsiz = reallocate_integer_array( accsiz, current_max_dfas );
- X dhash = reallocate_integer_array( dhash, current_max_dfas );
- X todo = reallocate_integer_array( todo, current_max_dfas );
- X dss = reallocate_integer_pointer_array( dss, current_max_dfas );
- X dfaacc = reallocate_dfaacc_union( dfaacc, current_max_dfas );
- X
- X /* fix up todo queue */
- X if ( todo_next < todo_head )
- X { /* queue was wrapped around the end */
- X register int i;
- X
- X for ( i = 0; i < todo_next; ++i )
- X todo[old_max + i] = todo[i];
- X
- X todo_next += old_max;
- X }
- X }
- X
- X
- X/* snstods - converts a set of ndfa states into a dfa state
- X *
- X * synopsis
- X * int sns[numstates], numstates, newds, accset[accnum + 1], nacc, hashval;
- X * int snstods();
- X * is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
- X *
- X * on return, the dfa state number is in newds.
- X */
- X
- int snstods( sns, numstates, accset, nacc, hashval, newds_addr )
- int sns[], numstates, accset[], nacc, hashval, *newds_addr;
- X
- X {
- X int didsort = 0;
- X register int i, j;
- X int newds, *oldsns;
- X char *malloc();
- X
- X for ( i = 1; i <= lastdfa; ++i )
- X if ( hashval == dhash[i] )
- X {
- X if ( numstates == dfasiz[i] )
- X {
- X oldsns = dss[i];
- X
- X if ( ! didsort )
- X {
- X /* we sort the states in sns so we can compare it to
- X * oldsns quickly. we use bubble because there probably
- X * aren't very many states
- X */
- X bubble( sns, numstates );
- X didsort = 1;
- X }
- X
- X for ( j = 1; j <= numstates; ++j )
- X if ( sns[j] != oldsns[j] )
- X break;
- X
- X if ( j > numstates )
- X {
- X ++dfaeql;
- X *newds_addr = i;
- X return ( 0 );
- X }
- X
- X ++hshcol;
- X }
- X
- X else
- X ++hshsave;
- X }
- X
- X /* make a new dfa */
- X
- X if ( ++lastdfa >= current_max_dfas )
- X increase_max_dfas();
- X
- X newds = lastdfa;
- X
- X if ( ! (dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) )) )
- X flexfatal( "dynamic memory failure in snstods()" );
- X
- X /* if we haven't already sorted the states in sns, we do so now, so that
- X * future comparisons with it can be made quickly
- X */
- X
- X if ( ! didsort )
- X bubble( sns, numstates );
- X
- X for ( i = 1; i <= numstates; ++i )
- X dss[newds][i] = sns[i];
- X
- X dfasiz[newds] = numstates;
- X dhash[newds] = hashval;
- X
- X if ( nacc == 0 )
- X {
- X dfaacc[newds].dfaacc_state = 0;
- X accsiz[newds] = 0;
- X }
- X
- X else if ( reject )
- X {
- X /* we sort the accepting set in increasing order so the disambiguating
- X * rule that the first rule listed is considered match in the event of
- X * ties will work. We use a bubble sort since the list is probably
- X * quite small.
- X */
- X
- X bubble( accset, nacc );
- X
- X dfaacc[newds].dfaacc_state =
- X (int) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
- X
- X if ( ! dfaacc[newds].dfaacc_state )
- X flexfatal( "dynamic memory failure in snstods()" );
- X
- X /* save the accepting set for later */
- X for ( i = 1; i <= nacc; ++i )
- X dfaacc[newds].dfaacc_set[i] = accset[i];
- X
- X accsiz[newds] = nacc;
- X }
- X
- X else
- X { /* find lowest numbered rule so the disambiguating rule will work */
- X j = accnum + 1;
- X
- X for ( i = 1; i <= nacc; ++i )
- X if ( accset[i] < j )
- X j = accset[i];
- X
- X dfaacc[newds].dfaacc_state = j;
- X }
- X
- X *newds_addr = newds;
- X
- X return ( 1 );
- X }
- X
- X
- X/* symfollowset - follow the symbol transitions one step
- X *
- X * synopsis
- X * int ds[current_max_dfa_size], dsize, transsym;
- X * int nset[current_max_dfa_size], numstates;
- X * numstates = symfollowset( ds, dsize, transsym, nset );
- X */
- X
- int symfollowset( ds, dsize, transsym, nset )
- int ds[], dsize, transsym, nset[];
- X
- X {
- X int ns, tsp, sym, i, j, lenccl, ch, numstates;
- X int ccllist;
- X
- X numstates = 0;
- X
- X for ( i = 1; i <= dsize; ++i )
- X { /* for each nfa state ns in the state set of ds */
- X ns = ds[i];
- X sym = transchar[ns];
- X tsp = trans1[ns];
- X
- X if ( sym < 0 )
- X { /* it's a character class */
- X sym = -sym;
- X ccllist = cclmap[sym];
- X lenccl = ccllen[sym];
- X
- X if ( cclng[sym] )
- X {
- X for ( j = 0; j < lenccl; ++j )
- X { /* loop through negated character class */
- X ch = ccltbl[ccllist + j];
- X
- X if ( ch > transsym )
- X break; /* transsym isn't in negated ccl */
- X
- X else if ( ch == transsym )
- X /* next 2 */ goto bottom;
- X }
- X
- X /* didn't find transsym in ccl */
- X nset[++numstates] = tsp;
- X }
- X
- X else
- X for ( j = 0; j < lenccl; ++j )
- X {
- X ch = ccltbl[ccllist + j];
- X
- X if ( ch > transsym )
- X break;
- X
- X else if ( ch == transsym )
- X {
- X nset[++numstates] = tsp;
- X break;
- X }
- X }
- X }
- X
- X else if ( sym >= 'A' && sym <= 'Z' && caseins )
- X flexfatal( "consistency check failed in symfollowset" );
- X
- X else if ( sym == SYM_EPSILON )
- X { /* do nothing */
- X }
- X
- X else if ( ecgroup[sym] == transsym )
- X nset[++numstates] = tsp;
- X
- bottom:
- X ;
- X }
- X
- X return ( numstates );
- X }
- X
- X
- X/* sympartition - partition characters with same out-transitions
- X *
- X * synopsis
- X * integer ds[current_max_dfa_size], numstates, duplist[numecs];
- X * symlist[numecs];
- X * sympartition( ds, numstates, symlist, duplist );
- X */
- X
- sympartition( ds, numstates, symlist, duplist )
- int ds[], numstates, duplist[];
- int symlist[];
- X
- X {
- X int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
- X
- X /* partitioning is done by creating equivalence classes for those
- X * characters which have out-transitions from the given state. Thus
- X * we are really creating equivalence classes of equivalence classes.
- X */
- X
- X for ( i = 1; i <= numecs; ++i )
- X { /* initialize equivalence class list */
- X duplist[i] = i - 1;
- X dupfwd[i] = i + 1;
- X }
- X
- X duplist[1] = NIL;
- X dupfwd[numecs] = NIL;
- X
- X for ( i = 1; i <= numstates; ++i )
- X {
- X ns = ds[i];
- X tch = transchar[ns];
- X
- X if ( tch != SYM_EPSILON )
- X {
- X if ( tch < -lastccl || tch > CSIZE )
- X flexfatal( "bad transition character detected in sympartition()" );
- X
- X if ( tch > 0 )
- X { /* character transition */
- X mkechar( ecgroup[tch], dupfwd, duplist );
- X symlist[ecgroup[tch]] = 1;
- X }
- X
- X else
- X { /* character class */
- X tch = -tch;
- X
- X lenccl = ccllen[tch];
- X cclp = cclmap[tch];
- X mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs );
- X
- X if ( cclng[tch] )
- X {
- X j = 0;
- X
- X for ( k = 0; k < lenccl; ++k )
- X {
- X ich = ccltbl[cclp + k];
- X
- X for ( ++j; j < ich; ++j )
- X symlist[j] = 1;
- X }
- X
- X for ( ++j; j <= numecs; ++j )
- X symlist[j] = 1;
- X }
- X
- X else
- X for ( k = 0; k < lenccl; ++k )
- X {
- X ich = ccltbl[cclp + k];
- X symlist[ich] = 1;
- X }
- X }
- X }
- X }
- X }
- END_OF_FILE
- if test 10732 -ne `wc -c <'dfa.c'`; then
- echo shar: \"'dfa.c'\" unpacked with wrong size!
- fi
- # end of 'dfa.c'
- fi
- if test -f 'flex.fastskel' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'flex.fastskel'\"
- else
- echo shar: Extracting \"'flex.fastskel'\" \(9304 characters\)
- sed "s/^X//" >'flex.fastskel' <<'END_OF_FILE'
- X/* A lexical scanner generated by flex */
- X
- X#define FLEX_FAST_SKEL
- X
- X#include "fastskeldef.h"
- X
- X%% section 1 code and the definition of YY_TRANS_OFFSET_TYPE, if needed, go here
- X
- X#ifndef FLEX_FULL_TABLE
- X /* struct for yy_transition */
- X struct yy_trans_info
- X {
- X /* v is a verify for a transition. */
- X short v;
- X
- X /* In cases where its sister v *is* a "yes, there is a transition",
- X * n is* the offset (in records) to the next state. In most cases
- X * where there is no transition, the value of n is irrelevant. If n
- X * is the -1th record of a state, though, then n is the action
- X * number for that state
- X */
- X YY_TRANS_OFFSET_TYPE n;
- X };
- X#endif
- X
- X%% data tables for DFA go here
- X
- X/* these declarations have to come after the section 1 code or lint gets
- X * confused about whether the variables are used
- X */
- XFILE *yyin = stdin, *yyout = stdout;
- X
- X/* these variables are all declared out here so that section 3 code can
- X * manipulate them
- X */
- static char *yy_c_buf_p; /* points to current character in buffer */
- static char *yy_b_buf_p; /* points to start of current scan */
- static int yy_init = 1; /* whether we need to initialize */
- static int yy_start; /* start state number */
- X
- X/* true when we've seen an EOF for the current input file */
- static int yy_eof_has_been_seen;
- X
- static int yy_n_chars; /* number of characters read into yy_ch_buf */
- X
- X/* yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need
- X * to put in 2 end-of-buffer characters (this is explained where it is
- X * done) at the end of yy_ch_buf
- X */
- static char yy_ch_buf[YY_BUF_SIZE + 2];
- X
- X/* yy_hold_char holds the character lost when yytext is formed */
- static char yy_hold_char;
- char *yytext;
- static int yyleng; /* length of yytext */
- X
- static YY_CS_TYPE yy_last_accepting_state;
- static char *yy_last_accepting_cpos;
- X
- static YY_CS_TYPE yy_get_previous_state();
- static int yy_get_next_buffer();
- X
- X#define FLEX_USES_BACKTRACKING
- X
- X#ifdef FLEX_USES_BACKTRACKING
- X# ifdef FLEX_FULL_TABLE
- X# define YY_BACKTRACKING_ACTION \
- X if ( l[yy_current_state] ) \
- X { \
- X yy_last_accepting_state = yy_current_state; \
- X yy_last_accepting_cpos = yy_c_buf_p; \
- X }
- X# else
- X# define YY_BACKTRACKING_ACTION \
- X if ( yy_current_state[-1].n ) \
- X { \
- X yy_last_accepting_state = yy_current_state; \
- X yy_last_accepting_cpos = yy_c_buf_p; \
- X }
- X# endif
- X#else
- X# define YY_BACKTRACKING_ACTION
- X#endif
- X
- YY_DECL
- X {
- X register YY_CS_TYPE yy_current_state;
- X register int yy_c;
- X register struct yy_trans_info *yy_trans_info;
- X register int yy_act;
- X
- X%% user's declarations go here
- X
- X if ( yy_init )
- X {
- X yy_start = 1; /* first start state */
- X
- new_file:
- X /* this is where we enter upon encountering and end-of-file and
- X * yywrap() indicating that we should continue processing
- X */
- X
- X /* we put in the '\n' and start reading from [1] so that an
- X * initial match-at-newline will be true.
- X */
- X
- X yy_ch_buf[0] = '\n';
- X yy_n_chars = 1;
- X
- X /* we always need two end-of-buffer characters. The first causes
- X * a transition to the end-of-buffer state. The second causes
- X * a jam in that state.
- X */
- X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
- X
- X yy_eof_has_been_seen = 0;
- X
- X YY_FAST_INIT;
- X yy_init = 0;
- X }
- X
- X while ( 1 ) /* loops until end-of-file is reached */
- X {
- X /* support of yytext and yyleng */
- X YY_DO_BEFORE_SCAN;
- X
- X /* yy_b_buf_p points to the position in yy_ch_buf of the start of the
- X * current run.
- X */
- X yy_b_buf_p = yy_c_buf_p;
- X
- X YY_FIND_START_STATE( yy_current_state );
- X
- X YY_FIND_NEXT_MATCH;
- X
- X YY_DO_BEFORE_ACTION;
- X
- X/* we need this label to process the very last action (right before the end of
- X * the file)
- X */
- do_action:
- X YY_FIND_ACTION( yy_act );
- X
- X#ifdef FLEX_DEBUG
- X fprintf( stderr, "--accepting rule #%d\n", yy_act );
- X#endif
- X switch ( yy_act )
- X {
- X%% actions go here
- X
- X case YY_BACK_TRACK:
- X YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
- X yy_c_buf_p = yy_last_accepting_cpos + 1;
- X yy_current_state = yy_last_accepting_state;
- X YY_DO_BEFORE_ACTION;
- X goto do_action;
- X
- X case YY_NEW_FILE:
- X break; /* begin reading from new file */
- X
- X case YY_DO_DEFAULT:
- X /* we have to eat up one character and recompute yytext and
- X * yyleng
- X */
- X YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
- X ++yy_c_buf_p;
- X YY_DO_BEFORE_ACTION;
- X YY_DEFAULT_ACTION;
- X break;
- X
- X case YY_END_OF_BUFFER:
- X YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
- X
- X switch ( yy_get_next_buffer() )
- X {
- X case EOB_ACT_END_OF_FILE:
- X {
- X if ( yywrap() )
- X {
- X /* note: because we've taken care in
- X * yy_get_next_buffer() to have set up yy_b_buf_p,
- X * we can now set up yy_c_buf_p so that if some
- X * total hoser (like flex itself) wants
- X * to call the scanner after we return the
- X * YY_NULL, it'll still work - another YY_NULL
- X * will get returned.
- X */
- X yy_c_buf_p = yy_b_buf_p;
- X return ( YY_NULL );
- X }
- X
- X else
- X goto new_file;
- X }
- X break;
- X
- X case EOB_ACT_RESTART_SCAN:
- X yy_c_buf_p = yy_b_buf_p;
- X
- X YY_DO_BEFORE_RESTART;
- X break;
- X
- X case EOB_ACT_LAST_MATCH:
- X yy_c_buf_p = &yy_ch_buf[yy_n_chars];
- X
- X yy_current_state = yy_get_previous_state();
- X
- X YY_DO_BEFORE_ACTION;
- X
- X goto do_action;
- X }
- X break;
- X
- X default:
- X printf( "action # %d\n", yy_act );
- X YY_FATAL_ERROR( "fatal flex scanner internal error" );
- X }
- X }
- X }
- X
- X
- X/* yy_get_next_buffer - try to read in new buffer
- X *
- X * synopsis
- X * int yy_get_next_buffer();
- X *
- X * returns a code representing an action
- X * EOB_ACT_LAST_MATCH -
- X * EOB_ACT_RESTART_SCAN - restart the scanner
- X * EOB_ACT_END_OF_FILE - end of file
- X */
- X
- static int yy_get_next_buffer()
- X
- X {
- X if ( yy_c_buf_p != &yy_ch_buf[yy_n_chars + 1] )
- X {
- X YY_FATAL_ERROR( "NULL in input" );
- X /*NOTREACHED*/
- X }
- X
- X else
- X { /* try to read more data */
- X register char *dest = yy_ch_buf;
- X register char *source = yy_b_buf_p - 1; /* copy prev. char, too */
- X register int number_to_move, i;
- X int ret_val;
- X
- X /* first move last chars to start of buffer */
- X number_to_move = yy_c_buf_p - yy_b_buf_p;
- X
- X for ( i = 0; i < number_to_move; ++i )
- X *(dest++) = *(source++);
- X
- X if ( yy_eof_has_been_seen )
- X /* don't do the read, it's not guaranteed to return an EOF,
- X * just force an EOF
- X */
- X yy_n_chars = 0;
- X
- X else
- X /* read in more data */
- X YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars,
- X YY_BUF_SIZE - number_to_move - 1 );
- X
- X if ( yy_n_chars == 0 )
- X {
- X if ( number_to_move == 1 )
- X ret_val = EOB_ACT_END_OF_FILE;
- X else
- X ret_val = EOB_ACT_LAST_MATCH;
- X
- X yy_eof_has_been_seen = 1;
- X }
- X
- X else
- X ret_val = EOB_ACT_RESTART_SCAN;
- X
- X yy_n_chars += number_to_move;
- X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
- X
- X /* yy_b_buf_p begins at the second character in
- X * yy_ch_buf; the first character is the one which
- X * preceded it before reading in the latest buffer;
- X * it needs to be kept around in case it's a
- X * newline, so yy_get_previous_state() will have
- X * with '^' rules active
- X */
- X
- X yy_b_buf_p = &yy_ch_buf[1];
- X
- X return ( ret_val );
- X }
- X }
- X
- X
- X/* yy_get_previous_state - get the state just before the eob char was reached
- X *
- X * synopsis
- X * YY_CS_TYPE yy_get_previous_state();
- X */
- X
- static YY_CS_TYPE yy_get_previous_state()
- X
- X {
- X register YY_CS_TYPE yy_cur_state;
- X register char *yy_temp_char_ptr;
- X
- X YY_FIND_START_STATE( yy_cur_state );
- X
- X for ( yy_temp_char_ptr = yy_b_buf_p; yy_temp_char_ptr < yy_c_buf_p; )
- X YY_GET_NEXT_STATE;
- X
- X return ( yy_cur_state );
- X }
- X
- X
- static unput( c )
- int c;
- X
- X {
- X YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
- X
- X if ( yy_c_buf_p < yy_ch_buf + 2 )
- X { /* need to shift things up to make room */
- X register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
- X register char *dest = &yy_ch_buf[YY_BUF_SIZE + 2];
- X register char *source = &yy_ch_buf[number_to_move];
- X
- X while ( source > yy_ch_buf )
- X *--dest = *--source;
- X
- X yy_c_buf_p += dest - source;
- X yy_b_buf_p += dest - source;
- X
- X if ( yy_c_buf_p < yy_ch_buf + 2 )
- X YY_FATAL_ERROR( "flex scanner push-back overflow" );
- X }
- X
- X if ( yy_c_buf_p > yy_b_buf_p && yy_c_buf_p[-1] == '\n' )
- X yy_c_buf_p[-2] = '\n';
- X
- X *--yy_c_buf_p = c;
- X
- X YY_DO_BEFORE_ACTION; /* set up yytext again */
- X }
- X
- X
- static int input()
- X
- X {
- X int c;
- X
- X YY_DO_BEFORE_SCAN;
- X
- X if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
- X { /* need more input */
- X yy_b_buf_p = yy_c_buf_p;
- X ++yy_c_buf_p;
- X
- X switch ( yy_get_next_buffer() )
- X {
- X /* this code, unfortunately, is somewhat redundant with
- X * that above
- X */
- X case EOB_ACT_END_OF_FILE:
- X {
- X if ( yywrap() )
- X {
- X yy_c_buf_p = yy_b_buf_p;
- X return ( EOF );
- X }
- X
- X yy_ch_buf[0] = '\n';
- X yy_n_chars = 1;
- X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
- X yy_eof_has_been_seen = 0;
- X
- X YY_FAST_INIT;
- X
- X return ( input() );
- X }
- X break;
- X
- X case EOB_ACT_RESTART_SCAN:
- X yy_c_buf_p = yy_b_buf_p;
- X break;
- X
- X case EOB_ACT_LAST_MATCH:
- X YY_FATAL_ERROR( "unexpected last match in input()" );
- X }
- X }
- X
- X c = *yy_c_buf_p++;
- X
- X YY_DO_BEFORE_RESTART;
- X
- X return ( c );
- X }
- END_OF_FILE
- if test 9304 -ne `wc -c <'flex.fastskel'`; then
- echo shar: \"'flex.fastskel'\" unpacked with wrong size!
- fi
- # end of 'flex.fastskel'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(12885 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X/* flex - tool to generate fast lexical analyzers
- X *
- X *
- X * Copyright (c) 1987, the University of California
- X *
- X * The United States Government has rights in this work pursuant to
- X * contract no. DE-AC03-76SF00098 between the United States Department of
- X * Energy and the University of California.
- X *
- X * This program may be redistributed. Enhancements and derivative works
- X * may be created provided the new works, if made available to the general
- X * public, are made available for use by anyone.
- X *
- X *
- X * ver date who remarks
- X * --- ---- ------ -------------------------------------------------------
- X * 04b 30sep87 kg, vp .implemented (part of) Van Jacobson's fast scanner design
- X * 04a 27jun86 vp .translated from Ratfor into C
- X * 01a 22aug83 vp .written. Original version by Jef Poskanzer.
- X */
- X
- X#include "flexdef.h"
- X
- X
- X/* these globals are all defined and commented in flexdef.h */
- int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
- int interactive, caseins, useecs, fulltbl, usemecs, reject;
- int fullspd, gen_line_dirs;
- int datapos, dataline, linenum;
- XFILE *skelfile = NULL;
- char *infilename = NULL;
- int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
- int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
- int current_mns;
- int accnum, *firstst, *lastst, *finalst, *transchar;
- int *trans1, *trans2, *accptnum, lastnfa;
- int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
- int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
- int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
- int tecbck[CSIZE + 1];
- int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
- int current_max_dfa_size, current_max_xpairs;
- int current_max_template_xpairs, current_max_dfas;
- int lastdfa, *nxt, *chk, *tnxt;
- int *base, *def, tblend, firstfree, numtemps, **dss, *dfasiz;
- union dfaacc_union *dfaacc;
- int *accsiz, *dhash, *todo, todo_head, todo_next, numas;
- int numsnpairs, jambase, jamstate;
- int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
- int current_max_ccl_tbl_size;
- char *ccltbl;
- char *starttime, *endtime, nmstr[MAXLINE];
- int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
- int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
- XFILE *temp_action_file;
- int end_of_buffer_state;
- char *action_file_name = "/tmp/flexXXXXXX";
- X
- X
- X/* flex - main program
- X *
- X * synopsis (from the shell)
- X * flex [-v] [file ...]
- X */
- X
- main( argc, argv )
- int argc;
- char **argv;
- X
- X {
- X flexinit( argc, argv );
- X
- X readin();
- X
- X if ( ! syntaxerror )
- X {
- X /* convert the ndfa to a dfa */
- X ntod();
- X
- X /* generate the C state transition tables from the DFA */
- X make_tables();
- X }
- X
- X /* note, flexend does not return. It exits with its argument as status. */
- X
- X flexend( 0 );
- X }
- X
- X
- X/* flexend - terminate flex
- X *
- X * synopsis
- X * int status;
- X * flexend( status );
- X *
- X * status is exit status.
- X *
- X * note
- X * This routine does not return.
- X */
- X
- flexend( status )
- int status;
- X
- X {
- X int tblsiz;
- X char *gettime();
- X
- X if ( skelfile != NULL )
- X (void) fclose( skelfile );
- X
- X if ( temp_action_file )
- X {
- X (void) fclose( temp_action_file );
- X (void) unlink( action_file_name );
- X }
- X
- X if ( printstats )
- X {
- X endtime = gettime();
- X
- X fprintf( stderr, "flex usage statistics:\n" );
- X fprintf( stderr, " started at %s, finished at %s\n",
- X starttime, endtime );
- X
- X fprintf( stderr, " %d/%d NFA states\n", lastnfa, current_mns );
- X fprintf( stderr, " %d/%d DFA states (%d words)\n", lastdfa,
- X current_max_dfas, totnst );
- X fprintf( stderr, " %d rules\n", accnum );
- X fprintf( stderr, " %d/%d start conditions\n", lastsc,
- X current_max_scs );
- X fprintf( stderr, " %d epsilon states, %d double epsilon states\n",
- X numeps, eps2 );
- X
- X if ( lastccl == 0 )
- X fprintf( stderr, " no character classes\n" );
- X else
- X fprintf( stderr,
- X " %d/%d character classes needed %d/%d words of storage, %d reused\n",
- X lastccl, current_maxccls,
- X cclmap[lastccl] + ccllen[lastccl] - 1,
- X current_max_ccl_tbl_size, cclreuse );
- X
- X fprintf( stderr, " %d state/nextstate pairs created\n", numsnpairs );
- X fprintf( stderr, " %d/%d unique/duplicate transitions\n",
- X numuniq, numdup );
- X
- X if ( fulltbl )
- X {
- X tblsiz = lastdfa * numecs;
- X fprintf( stderr, " %d table entries\n", tblsiz );
- X }
- X
- X else
- X {
- X tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
- X
- X fprintf( stderr, " %d/%d base/def entries created\n",
- X lastdfa + numtemps, current_max_dfas );
- X fprintf( stderr, " %d/%d (peak %d) nxt/chk entries created\n",
- X tblend, current_max_xpairs, peakpairs );
- X fprintf( stderr,
- X " %d/%d (peak %d) template nxt/chk entries created\n",
- X numtemps * nummecs, current_max_template_xpairs,
- X numtemps * numecs );
- X fprintf( stderr, " %d empty table entries\n", nummt );
- X fprintf( stderr, " %d protos created\n", numprots );
- X fprintf( stderr, " %d templates created, %d uses\n",
- X numtemps, tmpuses );
- X }
- X
- X if ( useecs )
- X {
- X tblsiz = tblsiz + CSIZE;
- X fprintf( stderr, " %d/%d equivalence classes created\n",
- X numecs, CSIZE );
- X }
- X
- X if ( usemecs )
- X {
- X tblsiz = tblsiz + numecs;
- X fprintf( stderr, " %d/%d meta-equivalence classes created\n",
- X nummecs, CSIZE );
- X }
- X
- X fprintf( stderr, " %d (%d saved) hash collisions, %d DFAs equal\n",
- X hshcol, hshsave, dfaeql );
- X fprintf( stderr, " %d sets of reallocations needed\n", num_reallocs );
- X fprintf( stderr, " %d total table entries needed\n", tblsiz );
- X }
- X
- X exit( status );
- X }
- X
- X
- X/* flexinit - initialize flex
- X *
- X * synopsis
- X * int argc;
- X * char **argv;
- X * flexinit( argc, argv );
- X */
- X
- flexinit( argc, argv )
- int argc;
- char **argv;
- X
- X {
- X int i, sawcmpflag, use_stdout;
- X char *arg, *skelname = NULL, *gettime(), clower(), *mktemp();
- X
- X printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
- X ddebug = fulltbl = reject = fullspd = false;
- X gen_line_dirs = usemecs = useecs = true;
- X
- X sawcmpflag = false;
- X use_stdout = false;
- X
- X /* read flags */
- X for ( --argc, ++argv; argc ; --argc, ++argv )
- X {
- X if ( argv[0][0] != '-' || argv[0][1] == '\0' )
- X break;
- X
- X arg = argv[0];
- X
- X for ( i = 1; arg[i] != '\0'; ++i )
- X switch ( arg[i] )
- X {
- X case 'c':
- X if ( i != 1 )
- X flexerror( "-c flag must be given separately" );
- X
- X if ( ! sawcmpflag )
- X {
- X useecs = false;
- X usemecs = false;
- X fulltbl = false;
- X sawcmpflag = true;
- X }
- X
- X for ( ++i; arg[i] != '\0'; ++i )
- X switch ( clower( arg[i] ) )
- X {
- X case 'e':
- X useecs = true;
- X break;
- X
- X case 'F':
- X fullspd = true;
- X break;
- X
- X case 'f':
- X fulltbl = true;
- X break;
- X
- X case 'm':
- X usemecs = true;
- X break;
- X
- X default:
- X lerrif( "unknown -c option %c",
- X (int) arg[i] );
- X break;
- X }
- X
- X goto get_next_arg;
- X
- X case 'd':
- X ddebug = true;
- X break;
- X
- X case 'f':
- X useecs = usemecs = false;
- X fulltbl = true;
- X break;
- X
- X case 'I':
- X interactive = true;
- X break;
- X
- X case 'i':
- X caseins = true;
- X break;
- X
- X case 'L':
- X gen_line_dirs = false;
- X break;
- X
- X case 'r':
- X reject = true;
- X break;
- X
- X case 'F':
- X useecs = usemecs = false;
- X fullspd = true;
- X break;
- X
- X case 'S':
- X if ( i != 1 )
- X flexerror( "-S flag must be given separately" );
- X
- X skelname = arg + i + 1;
- X goto get_next_arg;
- X
- X case 's':
- X spprdflt = true;
- X break;
- X
- X case 't':
- X use_stdout = true;
- X break;
- X
- X case 'T':
- X trace = true;
- X break;
- X
- X case 'v':
- X printstats = true;
- X break;
- X
- X default:
- X lerrif( "unknown flag %c", (int) arg[i] );
- X break;
- X }
- X
- get_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
- X ;
- X }
- X
- X if ( (fulltbl || fullspd) && usemecs )
- X flexerror( "full table and -cm don't make sense together" );
- X
- X if ( (fulltbl || fullspd) && interactive )
- X flexerror( "full table and -I are (currently) incompatible" );
- X
- X if ( (fulltbl || fullspd) && reject )
- X flexerror( "reject (-r) cannot be used with -f or -F" );
- X
- X if ( fulltbl && fullspd )
- X flexerror( "full table and -F are mutually exclusive" );
- X
- X if ( ! skelname )
- X {
- X static char skeleton_name_storage[400];
- X
- X skelname = skeleton_name_storage;
- X
- X if ( fullspd || fulltbl )
- X (void) strcpy( skelname, FAST_SKELETON_FILE );
- X else
- X (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
- X }
- X
- X if ( ! use_stdout )
- X {
- X FILE *prev_stdout = freopen( "lex.yy.c", "w", stdout );
- X
- X if ( prev_stdout == NULL )
- X flexerror( "could not create lex.yy.c" );
- X }
- X
- X if ( argc )
- X {
- X if ( argc > 1 )
- X flexerror( "extraneous argument(s) given" );
- X
- X yyin = fopen( infilename = argv[0], "r" );
- X
- X if ( yyin == NULL )
- X lerrsf( "can't open %s", argv[0] );
- X }
- X
- X else
- X yyin = stdin;
- X
- X lastccl = 0;
- X lastsc = 0;
- X
- X /* initialize the statistics */
- X starttime = gettime();
- X
- X if ( (skelfile = fopen( skelname, "r" )) == NULL )
- X lerrsf( "can't open skeleton file %s", skelname );
- X
- X (void) mktemp( action_file_name );
- X
- X if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
- X lerrsf( "can't open temporary action file %s", action_file_name );
- X
- X lastdfa = lastnfa = accnum = numas = numsnpairs = tmpuses = 0;
- X numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
- X numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
- X onesp = numprots = 0;
- X
- X linenum = sectnum = 1;
- X firstprot = NIL;
- X
- X /* used in mkprot() so that the first proto goes in slot 1
- X * of the proto queue
- X */
- X lastprot = 1;
- X
- X if ( useecs )
- X {
- X /* set up doubly-linked equivalence classes */
- X ecgroup[1] = NIL;
- X
- X for ( i = 2; i <= CSIZE; ++i )
- X {
- X ecgroup[i] = i - 1;
- X nextecm[i - 1] = i;
- X }
- X
- X nextecm[CSIZE] = NIL;
- X }
- X
- X else
- X { /* put everything in its own equivalence class */
- X for ( i = 1; i <= CSIZE; ++i )
- X {
- X ecgroup[i] = i;
- X nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */
- X }
- X }
- X
- X set_up_initial_allocations();
- X }
- X
- X
- X/* readin - read in the rules section of the input file(s)
- X *
- X * synopsis
- X * readin();
- X */
- X
- readin()
- X
- X {
- X fputs( "#define YY_DEFAULT_ACTION ", stdout );
- X
- X if ( spprdflt )
- X fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", stdout );
- X else
- X fputs( "ECHO", stdout );
- X
- X fputs( ";\n", stdout );
- X
- X if ( ddebug )
- X puts( "#define FLEX_DEBUG" );
- X if ( useecs )
- X puts( "#define FLEX_USE_ECS" );
- X if ( usemecs )
- X puts( "#define FLEX_USE_MECS" );
- X if ( interactive )
- X puts( "#define FLEX_INTERACTIVE_SCANNER" );
- X if ( reject )
- X puts( "#define FLEX_REJECT_ENABLED" );
- X if ( fulltbl )
- X puts( "#define FLEX_FULL_TABLE" );
- X
- X skelout();
- X
- X line_directive_out( stdout );
- X
- X if ( yyparse() )
- X lerrif( "fatal parse error at line %d", linenum );
- X
- X if ( useecs )
- X {
- X numecs = cre8ecs( nextecm, ecgroup, CSIZE );
- X ccl2ecl();
- X }
- X
- X else
- X numecs = CSIZE;
- X
- X }
- X
- X
- X
- X/* set_up_initial_allocations - allocate memory for internal tables */
- X
- set_up_initial_allocations()
- X
- X {
- X current_mns = INITIAL_MNS;
- X firstst = allocate_integer_array( current_mns );
- X lastst = allocate_integer_array( current_mns );
- X finalst = allocate_integer_array( current_mns );
- X transchar = allocate_integer_array( current_mns );
- X trans1 = allocate_integer_array( current_mns );
- X trans2 = allocate_integer_array( current_mns );
- X accptnum = allocate_integer_array( current_mns );
- X
- X current_max_scs = INITIAL_MAX_SCS;
- X scset = allocate_integer_array( current_max_scs );
- X scbol = allocate_integer_array( current_max_scs );
- X scxclu = allocate_integer_array( current_max_scs );
- X actvsc = allocate_integer_array( current_max_scs );
- X
- X current_maxccls = INITIAL_MAXCCLS;
- X cclmap = allocate_integer_array( current_maxccls );
- X ccllen = allocate_integer_array( current_maxccls );
- X cclng = allocate_integer_array( current_maxccls );
- X
- X current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
- X ccltbl = allocate_character_array( current_max_ccl_tbl_size );
- X
- X current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
- X
- X current_max_xpairs = INITIAL_MAX_XPAIRS;
- X nxt = allocate_integer_array( current_max_xpairs );
- X chk = allocate_integer_array( current_max_xpairs );
- X
- X current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
- X tnxt = allocate_integer_array( current_max_template_xpairs );
- X
- X current_max_dfas = INITIAL_MAX_DFAS;
- X base = allocate_integer_array( current_max_dfas );
- X def = allocate_integer_array( current_max_dfas );
- X dfasiz = allocate_integer_array( current_max_dfas );
- X accsiz = allocate_integer_array( current_max_dfas );
- X dhash = allocate_integer_array( current_max_dfas );
- X todo = allocate_integer_array( current_max_dfas );
- X dss = allocate_integer_pointer_array( current_max_dfas );
- X dfaacc = allocate_dfaacc_union( current_max_dfas );
- X }
- END_OF_FILE
- if test 12885 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'misc.c'\"
- else
- echo shar: Extracting \"'misc.c'\" \(9991 characters\)
- sed "s/^X//" >'misc.c' <<'END_OF_FILE'
- X/* misc - miscellaneous flex routines */
- X
- X/*
- X * Copyright (c) 1987, the University of California
- X *
- X * The United States Government has rights in this work pursuant to
- X * contract no. DE-AC03-76SF00098 between the United States Department of
- X * Energy and the University of California.
- X *
- X * This program may be redistributed. Enhancements and derivative works
- X * may be created provided the new works, if made available to the general
- X * public, are made available for use by anyone.
- X */
- X
- X#include <ctype.h>
- X#include "flexdef.h"
- X
- char *malloc(), *realloc();
- X
- X
- X/* action_out - write the actions from the temporary file to lex.yy.c
- X *
- X * synopsis
- X * action_out();
- X *
- X * Copies the action file up to %% (or end-of-file) to lex.yy.c
- X */
- X
- action_out()
- X
- X {
- X char buf[MAXLINE];
- X
- X while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
- X if ( buf[0] == '%' && buf[1] == '%' )
- X break;
- X else
- X fputs( buf, stdout );
- X }
- X
- X
- X/* allocate_array - allocate memory for an integer array of the given size */
- X
- char *allocate_array( size, element_size )
- int size, element_size;
- X
- X {
- X register char *mem = malloc( (unsigned) (element_size * size) );
- X
- X if ( mem == NULL )
- X flexfatal( "memory allocation failed in allocate_array()" );
- X
- X return ( mem );
- X }
- X
- X
- X/* bubble - bubble sort an integer array in increasing order
- X *
- X * synopsis
- X * int v[n], n;
- X * bubble( v, n );
- X *
- X * description
- X * sorts the first n elements of array v and replaces them in
- X * increasing order.
- X *
- X * passed
- X * v - the array to be sorted
- X * n - the number of elements of 'v' to be sorted */
- X
- bubble( v, n )
- int v[], n;
- X
- X {
- X register int i, j, k;
- X
- X for ( i = n; i > 1; --i )
- X for ( j = 1; j < i; ++j )
- X if ( v[j] > v[j + 1] ) /* compare */
- X {
- X k = v[j]; /* exchange */
- X v[j] = v[j + 1];
- X v[j + 1] = k;
- X }
- X }
- X
- X
- X/* clower - replace upper-case letter to lower-case
- X *
- X * synopsis:
- X * char clower(), c;
- X * c = clower( c );
- X */
- X
- char clower( c )
- register char c;
- X
- X {
- X return ( isupper(c) ? tolower(c) : c );
- X }
- X
- X
- X/* copy_string - returns a dynamically allocated copy of a string
- X *
- X * synopsis
- X * char *str, *copy, *copy_string();
- X * copy = copy_string( str );
- X */
- X
- char *copy_string( str )
- register char *str;
- X
- X {
- X register char *c;
- X char *copy;
- X
- X /* find length */
- X for ( c = str; *c; ++c )
- X ;
- X
- X copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
- X
- X if ( copy == NULL )
- X flexfatal( "dynamic memory failure in copy_string()" );
- X
- X for ( c = copy; (*c++ = *str++); )
- X ;
- X
- X return ( copy );
- X }
- X
- X
- X/* cshell - shell sort a character array in increasing order
- X *
- X * synopsis
- X *
- X * char v[n];
- X * int n;
- X * cshell( v, n );
- X *
- X * description
- X * does a shell sort of the first n elements of array v.
- X *
- X * passed
- X * v - array to be sorted
- X * n - number of elements of v to be sorted
- X */
- cshell( v, n )
- char v[];
- int n;
- X
- X {
- X int gap, i, j, jg;
- X char k;
- X
- X for ( gap = n / 2; gap > 0; gap = gap / 2 )
- X for ( i = gap; i < n; ++i )
- X for ( j = i - gap; j >= 0; j = j - gap )
- X {
- X jg = j + gap;
- X
- X if ( v[j] <= v[jg] )
- X break;
- X
- X k = v[j];
- X v[j] = v[jg];
- X v[jg] = k;
- X }
- X }
- X
- X
- X/* dataend - finish up a block of data declarations
- X *
- X * synopsis
- X * dataend();
- X */
- dataend()
- X
- X {
- X if ( datapos > 0 )
- X dataflush();
- X
- X /* add terminator for initialization */
- X puts( " } ;\n" );
- X
- X dataline = 0;
- X }
- X
- X
- X
- X/* dataflush - flush generated data statements
- X *
- X * synopsis
- X * dataflush();
- X */
- dataflush()
- X
- X {
- X putchar( '\n' );
- X
- X if ( ++dataline >= NUMDATALINES )
- X {
- X /* put out a blank line so that the table is grouped into
- X * large blocks that enable the user to find elements easily
- X */
- X putchar( '\n' );
- X dataline = 0;
- X }
- X
- X /* reset the number of characters written on the current line */
- X datapos = 0;
- X }
- X
- X/* gettime - return current time
- X *
- X * synopsis
- X * char *gettime(), *time_str;
- X * time_str = gettime();
- X */
- X
- X/* include sys/types.h to use time_t and make lint happy */
- X
- X#include <sys/types.h>
- X
- char *gettime()
- X
- X {
- X time_t t, time();
- X char *result, *ctime(), *copy_string();
- X
- X t = time( (long *) 0 );
- X
- X result = copy_string( ctime( &t ) );
- X
- X /* get rid of trailing newline */
- X result[24] = '\0';
- X
- X return ( result );
- X }
- X
- X
- X/* lerrif - report an error message formatted with one integer argument
- X *
- X * synopsis
- X * char msg[];
- X * int arg;
- X * lerrif( msg, arg );
- X */
- X
- lerrif( msg, arg )
- char msg[];
- int arg;
- X
- X {
- X char errmsg[MAXLINE];
- X (void) sprintf( errmsg, msg, arg );
- X flexerror( errmsg );
- X }
- X
- X
- X/* lerrsf - report an error message formatted with one string argument
- X *
- X * synopsis
- X * char msg[], arg[];
- X * lerrsf( msg, arg );
- X */
- X
- lerrsf( msg, arg )
- char msg[], arg[];
- X
- X {
- X char errmsg[MAXLINE];
- X
- X (void) sprintf( errmsg, msg, arg );
- X flexerror( errmsg );
- X }
- X
- X
- X/* flexerror - report an error message and terminate
- X *
- X * synopsis
- X * char msg[];
- X * flexerror( msg );
- X */
- X
- flexerror( msg )
- char msg[];
- X
- X {
- X fprintf( stderr, "flex: %s\n", msg );
- X flexend( 1 );
- X }
- X
- X
- X/* flexfatal - report a fatal error message and terminate
- X *
- X * synopsis
- X * char msg[];
- X * flexfatal( msg );
- X */
- X
- flexfatal( msg )
- char msg[];
- X
- X {
- X fprintf( stderr, "flex: fatal internal error %s\n", msg );
- X flexend( 1 );
- X }
- X
- X
- X/* line_directive_out - spit out a "# line" statement */
- X
- line_directive_out( output_file_name )
- XFILE *output_file_name;
- X
- X {
- X if ( infilename && gen_line_dirs )
- X fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
- X }
- X
- X
- X/* mk2data - generate a data statement for a two-dimensional array
- X *
- X * synopsis
- X * int value;
- X * mk2data( value );
- X *
- X * generates a data statement initializing the current 2-D array to "value"
- X */
- mk2data( value )
- int value;
- X
- X {
- X if ( datapos >= NUMDATAITEMS )
- X {
- X putchar( ',' );
- X dataflush();
- X }
- X
- X if ( datapos == 0 )
- X /* indent */
- X fputs( " ", stdout );
- X
- X else
- X putchar( ',' );
- X
- X ++datapos;
- X
- X printf( "%5d", value );
- X }
- X
- X
- X/* mkdata - generate a data statement
- X *
- X * synopsis
- X * int value;
- X * mkdata( value );
- X *
- X * generates a data statement initializing the current array element to
- X * "value"
- X */
- mkdata( value )
- int value;
- X
- X {
- X if ( datapos >= NUMDATAITEMS )
- X {
- X putchar( ',' );
- X dataflush();
- X }
- X
- X if ( datapos == 0 )
- X /* indent */
- X fputs( " ", stdout );
- X
- X else
- X putchar( ',' );
- X
- X ++datapos;
- X
- X printf( "%5d", value );
- X }
- X
- X
- X/* myctoi - return the integer represented by a string of digits
- X *
- X * synopsis
- X * char array[];
- X * int val, myctoi();
- X * val = myctoi( array );
- X *
- X */
- X
- int myctoi( array )
- char array[];
- X
- X {
- X int val = 0;
- X
- X (void) sscanf( array, "%d", &val );
- X
- X return ( val );
- X }
- X
- X
- X/* myesc - return character corresponding to escape sequence
- X *
- X * synopsis
- X * char array[], c, myesc();
- X * c = myesc( array );
- X *
- X */
- X
- char myesc( array )
- char array[];
- X
- X {
- X switch ( array[1] )
- X {
- X case 'n': return ( '\n' );
- X case 't': return ( '\t' );
- X case 'f': return ( '\f' );
- X case 'r': return ( '\r' );
- X case 'b': return ( '\b' );
- X
- X case '0':
- X if ( isdigit(array[2]) )
- X { /* \0<octal> */
- X char c, esc_char;
- X register int sptr = 2;
- X
- X while ( isdigit(array[sptr]) )
- X /* don't increment inside loop control because the
- X * macro will expand it to two increments! (Not a
- X * problem with the C version of the macro)
- X */
- X ++sptr;
- X
- X c = array[sptr];
- X array[sptr] = '\0';
- X
- X esc_char = otoi( array + 2 );
- X array[sptr] = c;
- X
- X if ( esc_char == '\0' )
- X {
- X synerr( "escape sequence for null not allowed" );
- X return ( 1 );
- X }
- X
- X return ( esc_char );
- X }
- X
- X else
- X {
- X synerr( "escape sequence for null not allowed" );
- X return ( 1 );
- X }
- X
- X#ifdef NOTDEF
- X case '^':
- X {
- X register char next_char = array[2];
- X
- X if ( next_char == '?' )
- X return ( 0x7f );
- X
- X else if ( next_char >= 'A' && next_char <= 'Z' )
- X return ( next_char - 'A' + 1 );
- X
- X else if ( next_char >= 'a' && next_char <= 'z' )
- X return ( next_char - 'z' + 1 );
- X
- X synerr( "illegal \\^ escape sequence" );
- X
- X return ( 1 );
- X }
- X#endif
- X }
- X
- X return ( array[1] );
- X }
- X
- X
- X/* otoi - convert an octal digit string to an integer value
- X *
- X * synopsis:
- X * int val, otoi();
- X * char str[];
- X * val = otoi( str );
- X */
- X
- int otoi( str )
- char str[];
- X
- X {
- X#ifdef FTLSOURCE
- X fortran int gctoi()
- X int dummy = 1;
- X
- X return ( gctoi( str, dummy, 8 ) );
- X#else
- X int result;
- X
- X (void) sscanf( str, "%o", &result );
- X
- X return ( result );
- X#endif
- X }
- X
- X
- X
- X
- X/* reallocate_array - increase the size of a dynamic array */
- X
- char *reallocate_array( array, size, element_size )
- char *array;
- int size, element_size;
- X
- X {
- X register char *new_array = realloc( array,
- X (unsigned) (size * element_size ));
- X
- X if ( new_array == NULL )
- X flexfatal( "attempt to increase array size failed" );
- X
- X return ( new_array );
- X }
- X
- X
- X/* skelout - write out one section of the skeleton file
- X *
- X * synopsis
- X * skelout();
- X *
- X * DESCRIPTION
- X * Copies from skelfile to stdout until a line beginning with "%%" or
- X * EOF is found.
- X */
- skelout()
- X
- X {
- X char buf[MAXLINE];
- X
- X while ( fgets( buf, MAXLINE, skelfile ) != NULL )
- X if ( buf[0] == '%' && buf[1] == '%' )
- X break;
- X else
- X fputs( buf, stdout );
- X }
- X
- X
- X/* transition_struct_out - output a yy_trans_info structure
- X *
- X * synopsis
- X * int element_v, element_n;
- X * transition_struct_out( element_v, element_n );
- X *
- X * outputs the yy_trans_info structure with the two elements, element_v and
- X * element_n. Formats the output with spaces and carriage returns.
- X */
- X
- transition_struct_out( element_v, element_n )
- int element_v, element_n;
- X
- X {
- X printf( "%7d, %5d,", element_v, element_n );
- X
- X datapos += TRANS_STRUCT_PRINT_LENGTH;
- X
- X if ( datapos >= 75 )
- X {
- X printf( "\n" );
- X
- X if ( ++dataline % 10 == 0 )
- X printf( "\n" );
- X
- X datapos = 0;
- X }
- X }
- END_OF_FILE
- if test 9991 -ne `wc -c <'misc.c'`; then
- echo shar: \"'misc.c'\" unpacked with wrong size!
- fi
- # end of 'misc.c'
- fi
- if test -f 'scan.l' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'scan.l'\"
- else
- echo shar: Extracting \"'scan.l'\" \(9189 characters\)
- sed "s/^X//" >'scan.l' <<'END_OF_FILE'
- X/* scan.l - scanner for flex input */
- X
- X/*
- X * Copyright (c) 1987, the University of California
- X *
- X * The United States Government has rights in this work pursuant to
- X * contract no. DE-AC03-76SF00098 between the United States Department of
- X * Energy and the University of California.
- X *
- X * This program may be redistributed. Enhancements and derivative works
- X * may be created provided the new works, if made available to the general
- X * public, are made available for use by anyone.
- X */
- X
- X%{
- X#include "flexdef.h"
- X#include "parse.h"
- X
- X#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
- X#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
- X
- X#undef YY_DECL
- X#define YY_DECL \
- X int flexscan()
- X
- X#define RETURNCHAR \
- X yylval = yytext[0]; \
- X return ( CHAR );
- X
- X#define RETURNNAME \
- X (void) strcpy( nmstr, yytext ); \
- X return ( NAME );
- X
- X#define PUT_BACK_STRING(str, start) \
- X for ( i = strlen( str ) - 1; i >= start; --i ) \
- X unput(str[i])
- X%}
- X
- X%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
- X%x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
- X%x ACTION_STRING PERCENT_BRACE_ACTION
- X
- WS [ \t]+
- X
- OPTWS [ \t]*
- X
- NAME [a-z_][a-z_0-9]*
- X
- SCNAME {NAME}
- X
- ESCSEQ \\([^^\n]|"^".|0[0-9]{1,3})
- X
- X%%
- X static int bracelevel, didadef;
- X int i, cclval;
- X char nmdef[MAXLINE], myesc();
- X
- X^{WS}.*\n ++linenum; ECHO; /* indented code */
- X^#.*\n ++linenum; ECHO; /* treat as a comment */
- X^"/*" ECHO; BEGIN(C_COMMENT);
- X^"%s"(tart)? return ( SCDECL );
- X^"%x" return ( XSCDECL );
- X^"%{".*\n ++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
- X{WS} return ( WHITESPACE );
- X
- X^"%%".* {
- X sectnum = 2;
- X line_directive_out( stdout );
- X BEGIN(SECT2PROLOG);
- X return ( SECTEND );
- X }
- X
- X^"%"[^sx{%].*\n {
- X fprintf( stderr,
- X "old-style lex command at line %d ignored:\n\t%s",
- X linenum, yytext );
- X ++linenum;
- X }
- X
- X^{NAME} {
- X (void) strcpy( nmstr, yytext );
- X didadef = false;
- X BEGIN(PICKUPDEF);
- X }
- X
- X{SCNAME} RETURNNAME;
- X^{OPTWS}\n ++linenum; /* allows blank lines in section 1 */
- X\n ++linenum; return ( '\n' );
- X. synerr( "illegal character" ); BEGIN(RECOVER);
- X
- X
- X<C_COMMENT>"*/" ECHO; BEGIN(0);
- X<C_COMMENT>"*/".*\n ++linenum; ECHO; BEGIN(0);
- X<C_COMMENT>[^*\n]+ ECHO;
- X<C_COMMENT>"*" ECHO;
- X<C_COMMENT>\n ++linenum; ECHO;
- X
- X<CODEBLOCK>^"%}".*\n ++linenum; BEGIN(0);
- X<CODEBLOCK>.*\n ++linenum; ECHO;
- X
- X<PICKUPDEF>{WS} /* separates name and definition */
- X
- X<PICKUPDEF>[^ \t\n].* {
- X (void) strcpy( nmdef, yytext );
- X
- X for ( i = strlen( nmdef ) - 1;
- X i >= 0 &&
- X nmdef[i] == ' ' || nmdef[i] == '\t';
- X --i )
- X ;
- X
- X nmdef[i + 1] = '\0';
- X
- X ndinstal( nmstr, nmdef );
- X didadef = true;
- X }
- X
- X<PICKUPDEF>\n {
- X if ( ! didadef )
- X synerr( "incomplete name definition" );
- X BEGIN(0);
- X ++linenum;
- X }
- X
- X<RECOVER>.*\n ++linenum; BEGIN(0); RETURNNAME;
- X
- X
- X<SECT2PROLOG>.*\n/[^ \t\n] {
- X ++linenum;
- X ACTION_ECHO;
- X MARK_END_OF_PROLOG;
- X BEGIN(SECT2);
- X }
- X
- X<SECT2PROLOG>.*\n ++linenum; ACTION_ECHO;
- X
- X<SECT2>^{OPTWS}\n ++linenum; /* allow blank lines in section 2 */
- X
- X /* this horrible mess of a rule matches indented lines which
- X * do not contain "/*". We need to make the distinction because
- X * otherwise this rule will be taken instead of the rule which
- X * matches the beginning of comments like this one
- X */
- X<SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n {
- X synerr( "indented code found outside of action" );
- X ++linenum;
- X }
- X
- X<SECT2>"<" BEGIN(SC); return ( '<' );
- X<SECT2>^"^" return ( '^' );
- X<SECT2>\" BEGIN(QUOTE); return ( '"' );
- X<SECT2>"{"/[0-9] BEGIN(NUM); return ( '{' );
- X<SECT2>"{"[^0-9\n][^}\n]* BEGIN(BRACEERROR);
- X<SECT2>"$"/[ \t\n] return ( '$' );
- X
- X<SECT2>{WS}"%{" {
- X bracelevel = 1;
- X BEGIN(PERCENT_BRACE_ACTION);
- X return ( '\n' );
- X }
- X<SECT2>{WS}"|".*\n ++linenum; return ( '\n' );
- X
- X<SECT2>^{OPTWS}"/*" ACTION_ECHO; BEGIN(C_COMMENT_2);
- X
- X<SECT2>{WS} { /* needs to be separate from following rule due to
- X * bug with trailing context
- X */
- X bracelevel = 0;
- X BEGIN(ACTION);
- X return ( '\n' );
- X }
- X
- X<SECT2>{OPTWS}/\n {
- X bracelevel = 0;
- X BEGIN(ACTION);
- X return ( '\n' );
- X }
- X
- X<SECT2>^{OPTWS}\n ++linenum; return ( '\n' );
- X
- X<SECT2>^"%%".* {
- X /* guarantee that the SECT3 rule will have something
- X * to match
- X */
- X yyless(1);
- X sectnum = 3;
- X BEGIN(SECT3);
- X return ( EOF ); /* to stop the parser */
- X }
- X
- X<SECT2>"["([^\\\]\n]|{ESCSEQ})+"]" {
- X (void) strcpy( nmstr, yytext );
- X
- X /* check to see if we've already encountered this ccl */
- X if ( (cclval = ccllookup( nmstr )) )
- X {
- X yylval = cclval;
- X ++cclreuse;
- X return ( PREVCCL );
- X }
- X else
- X {
- X /* we fudge a bit. We know that this ccl will
- X * soon be numbered as lastccl + 1 by cclinit
- X */
- X cclinstal( nmstr, lastccl + 1 );
- X
- X /* push back everything but the leading bracket
- X * so the ccl can be rescanned
- X */
- X PUT_BACK_STRING(nmstr, 1);
- X
- X BEGIN(FIRSTCCL);
- X return ( '[' );
- X }
- X }
- X
- X<SECT2>"{"{NAME}"}" {
- X register char *nmdefptr;
- X char *ndlookup();
- X
- X (void) strcpy( nmstr, yytext );
- X nmstr[yyleng - 1] = '\0'; /* chop trailing brace */
- X
- X /* lookup from "nmstr + 1" to chop leading brace */
- X if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
- X synerr( "undefined {name}" );
- X
- X else
- X { /* push back name surrounded by ()'s */
- X unput(')');
- X PUT_BACK_STRING(nmdefptr, 0);
- X unput('(');
- X }
- X }
- X
- X<SECT2>[/|*+?.()] return ( yytext[0] );
- X<SECT2>. RETURNCHAR;
- X<SECT2>\n ++linenum; return ( '\n' );
- X
- X
- X<SC>"," return ( ',' );
- X<SC>">" BEGIN(SECT2); return ( '>' );
- X<SC>">"/"^" BEGIN(CARETISBOL); return ( '>' );
- X<SC>{SCNAME} RETURNNAME;
- X<SC>. synerr( "bad start condition name" );
- X
- X<CARETISBOL>"^" BEGIN(SECT2); return ( '^' );
- X
- X
- X<QUOTE>[^"\n] RETURNCHAR;
- X<QUOTE>\" BEGIN(SECT2); return ( '"' );
- X
- X<QUOTE>\n {
- X synerr( "missing quote" );
- X BEGIN(SECT2);
- X ++linenum;
- X return ( '"' );
- X }
- X
- X
- X<FIRSTCCL>"^"/[^-\n] BEGIN(CCL); return ( '^' );
- X<FIRSTCCL>"^"/- return ( '^' );
- X<FIRSTCCL>- BEGIN(CCL); yylval = '-'; return ( CHAR );
- X<FIRSTCCL>. BEGIN(CCL); RETURNCHAR;
- X
- X<CCL>-/[^\]\n] return ( '-' );
- X<CCL>[^\]\n] RETURNCHAR;
- X<CCL>"]" BEGIN(SECT2); return ( ']' );
- X
- X
- X<NUM>[0-9]+ {
- X yylval = myctoi( yytext );
- X return ( NUMBER );
- X }
- X
- X<NUM>"," return ( ',' );
- X<NUM>"}" BEGIN(SECT2); return ( '}' );
- X
- X<NUM>. {
- X synerr( "bad character inside {}'s" );
- X BEGIN(SECT2);
- X return ( '}' );
- X }
- X
- X<NUM>\n {
- X synerr( "missing }" );
- X BEGIN(SECT2);
- X ++linenum;
- X return ( '}' );
- X }
- X
- X
- X<BRACEERROR>"}" synerr( "bad name in {}'s" ); BEGIN(SECT2);
- X<BRACEERROR>\n synerr( "missing }" ); ++linenum; BEGIN(SECT2);
- X
- X
- X<PERCENT_BRACE_ACTION>{OPTWS}"%}".* bracelevel = 0;
- X<PERCENT_BRACE_ACTION>.* ACTION_ECHO;
- X<PERCENT_BRACE_ACTION>\n {
- X ++linenum;
- X ACTION_ECHO;
- X if ( bracelevel == 0 )
- X {
- X fputs( "\tYY_BREAK\n", temp_action_file );
- X BEGIN(SECT2);
- X }
- X }
- X
- X<ACTION>"{" ACTION_ECHO; ++bracelevel;
- X<ACTION>"}" ACTION_ECHO; --bracelevel;
- X<ACTION>[^{}"'/\n]+ ACTION_ECHO;
- X<ACTION>"/*" ACTION_ECHO; BEGIN(ACTION_COMMENT);
- X<ACTION>"'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */
- X<ACTION>\" ACTION_ECHO; BEGIN(ACTION_STRING);
- X<ACTION>\n {
- X ++linenum;
- X ACTION_ECHO;
- X if ( bracelevel == 0 )
- X {
- X fputs( "\tYY_BREAK\n", temp_action_file );
- X BEGIN(SECT2);
- X }
- X }
- X<ACTION>. ACTION_ECHO;
- X
- X<ACTION_COMMENT>"*/" ACTION_ECHO; BEGIN(ACTION);
- X<ACTION_COMMENT>[^*\n]+ ACTION_ECHO;
- X<ACTION_COMMENT>"*" ACTION_ECHO;
- X<ACTION_COMMENT>\n ++linenum; ACTION_ECHO;
- X<ACTION_COMMENT>. ACTION_ECHO;
- X
- X<C_COMMENT_2>"*/" ACTION_ECHO; BEGIN(SECT2);
- X<C_COMMENT_2>"*/".*\n ++linenum; ACTION_ECHO; BEGIN(SECT2);
- X<C_COMMENT_2>[^*\n]+ ACTION_ECHO;
- X<C_COMMENT_2>"*" ACTION_ECHO;
- X<C_COMMENT_2>\n ++linenum; ACTION_ECHO;
- X
- X<ACTION_STRING>[^"\\\n]+ ACTION_ECHO;
- X<ACTION_STRING>\\. ACTION_ECHO;
- X<ACTION_STRING>\n ++linenum; ACTION_ECHO;
- X<ACTION_STRING>\" ACTION_ECHO; BEGIN(ACTION);
- X<ACTION_STRING>. ACTION_ECHO;
- X
- X
- X<SECT2,QUOTE,CCL>{ESCSEQ} {
- X yylval = myesc( yytext );
- X return ( CHAR );
- X }
- X
- X<FIRSTCCL>{ESCSEQ} {
- X yylval = myesc( yytext );
- X BEGIN(CCL);
- X return ( CHAR );
- X }
- X
- X
- X<SECT3>.|\n {
- X register int numchars;
- X
- X /* black magic - we know the names of a flex scanner's
- X * internal variables. We cap the input buffer with
- X * an end-of-string and dump it to the output.
- X */
- X YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
- X
- X#ifdef FLEX_FAST_SKEL
- X fputs( yy_c_buf_p + 1, stdout );
- X#else
- X yy_ch_buf[yy_e_buf_p + 1] = '\0';
- X
- X /* ignore the first character; it's the second '%'
- X * put back by the yyless(1) above
- X */
- X fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
- X#endif
- X
- X /* if we don't do this, the data written by write()
- X * can get overwritten when stdout is finally flushed
- X */
- X (void) fflush( stdout );
- X
- X while ( (numchars = read( fileno(yyin), yy_ch_buf,
- X YY_BUF_MAX )) > 0 )
- X (void) write( fileno(stdout), yy_ch_buf, numchars );
- X
- X if ( numchars < 0 )
- X flexerror( "fatal read error in section 3" );
- X
- X return ( EOF );
- X }
- X%%
- END_OF_FILE
- if test 9189 -ne `wc -c <'scan.l'`; then
- echo shar: \"'scan.l'\" unpacked with wrong size!
- fi
- # end of 'scan.l'
- fi
- echo shar: End of archive 2 \(of 5\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-